﻿using System;
using System.Collections.Generic;

/*
 * -- Pattern Responsibilities and Restrictions --
 * Definition: A layer of Mappers (473) that moves data between objects and a database while keeping them independent of each other and the mapper itself.
 * Mappers need a variety of strategies to handle classes that turn into multiple fields, classes that have multiple tables, classes with inheritance (1 class mapped to 2 db table having 1:1 relation)
 *  
 * 1. Complex type
 * 2. Foreign key parent/ (Foriegn key mapping pattern)
 * 3. Foreign key child/ Aggregate child
 * 4. Inheriance (in this case 1 class mapped to 2 db table having 1:1 relation)
 * 
 * Data Container:- 
 * Advanced *:* with database and data container
 * OPTIONAL: Data container names can be different
 * 
 * Data Container Fields:-
 * OPTIONAL: 1 data container field (value object/complex type) can be mapped to multiple database table fields
 * OPTIONAL: Extra fields are allowed on any side.
 * OPTIONAL: Field names can be different
 * OPTIONAL: Foreign key mapping to database fields
 * OPTIONAL: Computation can be implemented on fields (i.e. derived fields) 
 * OPTIONAL: Validation logic (i.e. email/phone format etc) on data fields
 * 
 * CRUD Method :-
 * REQUIRED: Data container and CRUD methods are placed in different class
 * RECOMMENDED: Insert/Update method type: instance/static
 * RECOMMENDED: Insert/Update method parameter - object
 * RECOMMENDED: Delete/Get method type: instance/static
 * RECOMMENDED: Delete/Get method parameter: By Id/Object etc
 * 
 * Business Logic :-
 * REQUIRED: Complex computational logic (non-field level) can be included
 * REQUIRED: Rransactional/workflow logic can be included, along with any domain layer pattern
 * 
*/

namespace DataMapperSample
{
    /// <summary>
    /// 1, complex type
    /// No database table underlying for it
    /// get mapped to five columns of a table
    /// this de-normalized approach is really useful in database level, that reduces joining (i.e performance)
    /// </summary>
    public class Address
    {
        public string AddressLine { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
        public string Country { get; set; }
    }

    public class Company
    {
        public int CompanyId { get; set; }
        public string CompanyName { get; set; }
        public Address CompanyAddress { get; set; }//1, complex type, that mapped to five columns of a table
        public IList<Employee> Employees { get; set; }//3, foreign key child table
    }

    public class Task
    {
        public int TaskId { get; set; }
        public string TaskName { get; set; }
        public DateTime TaskStarted { get; set; }
        public DateTime TaskEnded { get; set; }
        public Employee TaskAssignedTo { get; set; }//2, foreign key parent table
    }

    public class Person
    {
        public int PersonId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public Address HomeAddress { get; set; }//1, complex type, that mapped to five columns of a table 
    }

    public class Employee: Person//4, inheritance parent, in database level 1:1 relation on 2 database tables
    {
        public double MonthlySalary { get; set; }
        public Address EmargencyContactAddress { get; set; }//1, complex type, that mapped to five columns of a table 
        public Company Company { get; set; }//2, foreign key parent table/foreign key mapping 
        public  IList<Task> Tasks { get; set; }//3, foreign key child tables/these fields can also be considered as the aggregate childs
        public int ReportsTo { get; set; }//we can also use the direct foreign key reference, if we wish
        public Employee() {}

    }

    public class EmployeeDataMapper
    {
        //the crud methods can be static/instance
        public void Insert(Employee employee) { throw new NotImplementedException(); }
        public void Update(Employee employee) { throw new NotImplementedException(); }

        public void Delete(int EmployeeId) { throw new NotImplementedException(); }
        public void Delete(Employee employee) { throw new NotImplementedException(); }
        
        public Employee GetById(int EmployeeId) { throw new NotImplementedException(); }
        
        public IList<Employee> GetByCompanyId(int companyId) { throw new NotImplementedException(); }
        public IList<Employee> GetByCompany(Company company) { throw new NotImplementedException(); }
    }
}
